home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-28 | 16.3 KB | 640 lines | [TEXT/MPS ] |
- /*
- File: SprocketMain.cp
-
- Contains: The “guts” of a Macintosh application.
-
- Written by: Dave Falkenburg and many other SmartFriends™
-
- Copyright: © 1993-94 by Dave Falkenburg, all rights reserved.
-
- Change History (most recent first):
-
- <11> 11/16/94 DRF Added an explicit #include <Traps.h> for latest universal
- headers. Also killed off a CFront warning.
- <10> 11/12/94 DRF Revised QuickDrawGX initialization based on changes made by Jon
- Summer. We now use a 'gasz' resource to setup the size of the
- graphics heap. Also we are now always TSM aware, not just when
- TSMTE is around.
- <9> 11/8/94 DRF Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
- exists. Also, stop openning up the preferences file here.
- <8> 9/27/94 DRF AppLib.h is now Sprocket.h, also fixed scrap coercion routines
- and eliminated HandleUpdate.
- <7> 9/9/94 DRF Reordered headers and removed redundant #includes.
- Conditionalized AOCE support. Also made changes to
- TSMEventWrapper to be more like the code in InlineInputSample.
- <6> 9/8/94 DRF Add HiliteMenu(0) calls after calls to menu handling code
- because TSMMenuSelect doesn’t do it. Also reorganized some GX
- stuff: allocate and release a graphicsclient (Cam claims this
- works on his machine), and turn on all the graphics errors and
- notices if qDebug is set.
- <5> 9/7/94 DRF Rearrange YieldToAnyThread calls to make quitting faster.
- <4> 9/4/94 DRF Rearrange local variables in HandleMouseDown.
- <3> 9/1/94 DRF Stop including "MailableWindow.h" here.
- <2> 9/1/94 DRF More fixes for inline input, but we’re not really done yet.
- */
-
- #include "Sprocket.h"
-
- #include <limits.h> // For LONG_MAX
-
- #include <Fonts.h>
- #include <Desk.h>
- #include <GestaltEqu.h>
- #include <DiskInit.h>
- #include <Threads.h>
- #include <FragLoad.h> // for kUnresolvedSymbolAddress
- #include <Traps.h>
-
- #if qInlineInputAware
- #include <TextServices.h>
- #include <TSMTE.h>
- #endif
-
- #if qUseQuickDrawGX
- #include <graphics macintosh.h>
- #include <graphics routines.h>
- #include <graphics libraries.h>
- #include <PrintingManager.h>
- #endif
-
- #include "StandardMenus.h"
- #include "Window.h"
- #include "SplashWindow.h"
- #include "AppleEventHandling.h"
-
-
- // Function Prototypes
-
- void main(void);
- void MainEventLoop(void);
-
- void HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
- void HandleClose(WindowPtr aWindow);
-
-
- // Globals
-
- Boolean gDone = false;
- Boolean gMenuBarNeedsUpdate = true;
-
- Boolean gHasColorQuickdraw = false;
- Boolean gHasThreadManager = false;
- Boolean gHasDragManager = false;
- Boolean gHasAppleScript = false;
- Boolean gHasDisplayManager = false;
-
- GrafPtr gWindowManagerPort;
- Rect gDeskRectangle;
- RgnHandle gMouseRegion = nil;
-
- short gPreferencesRsrcRefNum;
-
- #if qAOCEAware
- Boolean gHasAOCE = false;
- #endif
-
- #if qInlineInputAware
- Boolean gHasTextServices = false;
- Boolean gHasTSMTE = false;
-
- Boolean TSMEventWrapperForKotoeri(EventRecord *anEvent);
-
- #endif
-
- #if qUseQuickDrawGX
- Boolean gHasQuickDrawGX = false;
- long gQuickDrawGXVersion = 0;
- long gQuickDrawGXPrintingVersion = 0;
- gxGraphicsClient gQuickDrawGXClient;
- #endif
-
-
- // Values that can be adjusted by other application code to change
- // the behavior of the MainEventLoop.
- //
- // Rules of thumb:
- //
- // Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
- // The application has many threads running that need time
- //
- // Decrease gXXXRunQuantum when:
- // Sending AppleEvents to other applications
- // Launching other applications
- // Running in the background
-
- unsigned long gForegroundRunQuantum = 0;
- unsigned long gForegroundSleepQuantum = GetCaretTime();
- unsigned long gBackgroundRunQuantum = 0;
- unsigned long gBackgroundSleepQuantum = LONG_MAX;
-
-
- // Globals used to “tune” the performance of MainEventLoop
- // (assume we’ll be starting in the foreground)
-
- static unsigned long gRunQuantum = gForegroundRunQuantum;
- static unsigned long gSleepQuantum = gForegroundSleepQuantum;
-
- #ifdef powerc
- #ifndef __MWERKS__
- QDGlobals qd;
- #endif
- #endif
-
- void
- main(void)
- {
- long feature;
-
- MaxApplZone();
- MoreMasters();
- MoreMasters();
- MoreMasters();
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
-
-
- if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
- FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
-
- if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
- gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
-
-
- TSplashWindow * splashWindow = new TSplashWindow;
-
- // Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
-
- #if qUseQuickDrawGX
- // Check for and initialize QuickDrawGX
- if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
- {
- if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
- {
- #if defined(__CFM68K__) || defined(__powerc)
- if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
- #endif
- gHasQuickDrawGX = true;
- }
- }
-
- if (gHasQuickDrawGX)
- {
- // Initialize the graphics and printing environments.
- // For additional details see "IM: QD GX Environment & Utilities."
-
- // We let QuickDraw GX look for a resource of type 'gasz' with an ID of 0.
- // GX uses the first long word of that resource as the graphics heap size.
- // To determine the memory requirements of your graphics client heap see:
- // “IM: QD GX Environment & Utilities pp2-8,2-9”
-
- // NOTE: If your application does not provide this resource,
- // QuickDraw GX version 1.0 uses a default size of 600 KB.
-
- gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
- if (gQuickDrawGXClient)
- {
- // NOTE: GXNewGraphicsClient() does not allocate memory to the heap
- // until GXEnterGraphics() is called, so go ahead and call it now
- // while we have a chance to deal with things nicely.
- //
- // NOTE: GXEnterGraphics() should only fail if there is not enough memory.
-
- GXEnterGraphics();
-
- if (GXGetGraphicsError(nil) == noErr)
- {
- #if qUseQuickDrawGXDebugging
- // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
-
- // NOTES from Jon Summers:
- // As you increase the amount of validation, drawing speed will SLOW
- // down due to all of the internal checking. Also, if you play with
- // settings enough validation seems to become inconsistent
-
- GXSetValidation( // gxInternalValidation |
- // gxAllObjectValidation |
- // gxApHeapValidation |
- gxPublicValidation); // check parameters to public routines
-
- // This functionality will only work with the "debugging" version of QuickDraw GX.
- // If you don't have the debugging version installed, these functions will not work.
-
- SetGraphicsLibraryErrors();
- SetGraphicsLibraryNotices();
- #endif
- if (GXInitPrinting() != noErr) // See IM: QuickDraw GX Printing
- {
- // We couldn’t initialize printing, so clean up pretend GX isn’t around
- // ••• For safety’s sake, we’ll probably want to bail here.
-
- if (gQuickDrawGXClient)
- GXDisposeGraphicsClient(gQuickDrawGXClient);
- gHasQuickDrawGX = false;
- }
- }
- }
- }
-
- if (gQuickDrawGXClient)
- InitCommonColors(); // Initialize the CommonColors Library.
- #if qRequireQuickDrawGX
- else
- FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
- #endif // qRequireQuickDrawGX
- #endif // qUseQuickDrawGX
-
-
- if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
- (feature & (1 << gestaltAppleEventsPresent)))
- {
- // Figure out if we need to do AppleEvent recording
- gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
- }
- else
- FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
-
- #if qInlineInputAware
- if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
- {
- gHasTextServices = true;
- if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
- gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
-
- if (InitTSMAwareApplication() != noErr)
- {
- gHasTextServices = false;
- gHasTSMTE = false;
- }
- }
-
- #endif
-
- if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
- {
- #if defined(__CFM68K__) || defined(__powerc)
- // If running on a PowerPC, make sure that we not only have the
- // 68K Thread Manager, but also the PowerPC shared library, too.
- // Because of the wonders of weak linking and out of memory errors
- // we need to also check to make sure that an entrypoint in the library
- // is there, too.
- if ((Ptr) NewThread != kUnresolvedSymbolAddress)
- gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
- #else
- gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
- #endif
- }
-
- #if qRequireThreadManager
- if (gHasThreadManager == false)
- FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
- #endif
-
- // Check for and install Drag Manager callbacks
- if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
- {
- #if defined(__CFM68K__) || defined(__powerc)
- // If running on a PowerPC, make sure that we not only have the
- // 68K Drag Manager, but also the PowerPC shared library, too.
- if ((Ptr) NewDrag != kUnresolvedSymbolAddress)
- gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
- #else
- gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
- #endif
-
- if (gHasDragManager)
- {
- InstallTrackingHandler( NewDragTrackingHandlerProc( CallWindowDragTrackingHandler ), ( WindowPtr )nil, nil );
- InstallReceiveHandler( NewDragReceiveHandlerProc( CallWindowDragReceiveHandler ), ( WindowPtr )nil, nil );
- }
- }
-
- // Check for Display Manager
- if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
- gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
-
- #if qAOCEAware
- // Check for and initialize AOCE Standard Mail package if it exists
- if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
- {
- #if defined(__CFM68K__) || defined(__powerc)
- if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
- gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
- #else
- gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
- #endif
- }
- #endif
-
- // Install our AppleEvent Handlers
- InstallAppleEventHandlers();
-
- // Setup desktop rectangle for dragging windows around
- GetWMgrPort(&gWindowManagerPort);
- gDeskRectangle = (**GetGrayRgn()).rgnBBox;
-
- // Get the default menubar
- SetMenuBar(GetNewMBar(rMenuBar));
- AddResMenu(GetMHandle(mApple),'DRVR');
-
- // Add fonts to the font menu if it installed
- if (GetMHandle(mFont))
- AddResMenu(GetMHandle(mFont),'FONT');
-
- if (SetupApplication() == noErr)
- {
- delete splashWindow; // get rid of the splash screen
- MainEventLoop();
- TearDownApplication();
- }
-
- #if qInlineInputAware
- if (gHasTextServices)
- (void) CloseTSMAwareApplication();
- #endif
-
- #if qUseQuickDrawGX
- // Tear down QuickDrawGX
- if (gHasQuickDrawGX && gQuickDrawGXClient)
- {
- DisposeCommonColors();
- GXExitPrinting(); // Close the new printing mgr.
- GXExitGraphics(); // Deallocate all of the default structures
- GXDisposeGraphicsClient(gQuickDrawGXClient);
- }
- #endif
- }
-
-
- void
- MainEventLoop(void)
- {
- EventRecord anEvent;
- unsigned long nextTimeToCheckForEvents = 0;
-
- while (!gDone)
- {
- if (gMenuBarNeedsUpdate)
- {
- gMenuBarNeedsUpdate = false;
- DrawMenuBar();
- }
-
- if (gHasThreadManager)
- YieldToAnyThread();
-
- if ((gRunQuantum == 0) ||
- (TickCount() > nextTimeToCheckForEvents))
- {
- nextTimeToCheckForEvents = TickCount() + gRunQuantum;
-
- (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
-
- #if qInlineInputAware
- if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
- {
- }
- else
- #endif
- HandleEvent(&anEvent);
- }
- }
- }
-
- #if qInlineInputAware
-
- Boolean
- TSMEventWrapperForKotoeri(EventRecord *anEvent)
- {
- short oldFont;
- ScriptCode keyboardScript;
- Boolean didTSMHandleTheEvent = false;
-
- // This snippet of code is from TE 27: Inline Input & TextEdit
- // and is related to working around a bug in Kotoeri, one of the
- // Japanese Input methods when operating in a mixed script
- // environment (e.g., Japanese Language Kit)
-
- // make sure we have a port and it's not the Window Manager port
- if (qd.thePort != nil)
- {
- oldFont = qd.thePort->txFont;
- keyboardScript = GetScriptManagerVariable(smKeyScript);
-
- if (FontToScript(oldFont) != keyboardScript)
- TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
- }
-
- didTSMHandleTheEvent = TSMEvent(anEvent);
-
- TextFont(oldFont); // restore the font, even though the sample code didn’t
-
- return didTSMHandleTheEvent;
- }
-
- #endif
-
-
-
- void
- HandleEvent(EventRecord *anEvent)
- {
- TWindow * wobj;
-
- if (anEvent->what != updateEvt)
- wobj = GetWindowObject(FrontNonFloatingWindow());
- else
- wobj = GetWindowObject((WindowPtr) anEvent->message);
-
- if (wobj != nil)
- #if qInlineInputAware
- // give text services a chance to set the cursor shape
- if (gHasTextServices && SetTSMCursor(anEvent->where))
- ; // do nothing, TSM did it for me
- else
- #endif
- wobj->AdjustCursor(anEvent);
-
- if ((wobj != nil) && wobj->EventFilter(anEvent))
- return;
-
- else switch (anEvent->what)
- {
- case nullEvent:
- if (wobj != nil)
- wobj->Idle(anEvent);
- break;
-
- case mouseDown:
- HandleMouseDown(wobj,anEvent);
- break;
-
- case keyDown:
- case autoKey:
- if (anEvent->modifiers & cmdKey)
- {
- long menuResult = MenuKey((short) anEvent->message & charCodeMask);
- #if qInlineInputAware
- if (!(gHasTextServices && TSMMenuSelect(menuResult)))
- #endif
- HandleMenu(wobj,menuResult);
- HiliteMenu(0);
- }
- else if (wobj != nil)
- wobj->KeyDown(anEvent);
- break;
-
- case updateEvt:
- {
- GrafPtr oldPort;
- WindowPtr aWindow = (WindowPtr) anEvent->message;
-
- GetPort(&oldPort);
- SetPort(aWindow);
- BeginUpdate(aWindow);
- if (wobj != nil)
- wobj->Draw();
- EndUpdate(aWindow);
- SetPort(oldPort);
- }
- break;
-
- case diskEvt:
- if (anEvent->message >> 16)
- {
- static Point where = {50,50};
- (void) DIBadMount(where,anEvent->message);
- }
- break;
-
- case osEvt:
- switch ((anEvent->message & osEvtMessageMask) >> 24)
- {
- case mouseMovedMessage:
- break;
-
- case suspendResumeMessage:
-
- SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
-
- if (anEvent->message & resumeFlag)
- {
- if (anEvent->message & convertClipboardFlag)
- ReadLocalClipboardFromScrap();
-
- gRunQuantum = gForegroundRunQuantum;
- gSleepQuantum = gForegroundSleepQuantum;
- }
- else
- {
- if (anEvent->message & convertClipboardFlag)
- WriteLocalClipboardToScrap();
- gRunQuantum = gBackgroundRunQuantum;
- gSleepQuantum = gBackgroundSleepQuantum;
- }
-
- break;
- }
- break;
-
- case kHighLevelEvent:
- (void) AEProcessAppleEvent(anEvent);
- break;
-
- default:
- break;
- }
- }
-
- void
- HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
- {
- WindowPtr aWindow;
- TWindow *wobj;
- short partCode;
-
- partCode = FindWindow(anEvent->where,&aWindow);
- wobj = GetWindowObject(aWindow);
- switch(partCode)
- {
- case inMenuBar:
- long menuResult = MenuSelect(anEvent->where);
- #if qInlineInputAware
- if (!(gHasTextServices && TSMMenuSelect(menuResult)))
- #endif
- HandleMenu(topWindowObj,menuResult);
- HiliteMenu(0);
- break;
-
- case inSysWindow:
- SystemClick(anEvent,aWindow);
- break;
-
- case inContent:
- if (wobj)
- {
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(aWindow);
- GlobalToLocal(&anEvent->where);
- wobj->Click(anEvent);
- SetPort(aWindow);
- }
- break;
-
- case inDrag:
- if (wobj)
- wobj->Drag(anEvent->where);
- break;
-
- case inGrow:
- if (wobj)
- wobj->Grow(anEvent->where);
- break;
-
- case inGoAway:
- if (TrackGoAway(aWindow,anEvent->where))
- HandleClose(aWindow);
- break;
-
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
- wobj->Zoom(partCode);
- break;
-
- default:
- break;
- }
- }
-
-
- void
- HandleClose(WindowPtr aWindow)
- {
- short windowKind;
- TWindow *wobj;
-
- if (aWindow)
- {
- windowKind = ((WindowPeek) aWindow)->windowKind;
- if (windowKind < 0)
- {
- CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
- }
- else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
- wobj->CanClose() &&
- wobj->Close() &&
- wobj->DeleteAfterClose())
- {
- delete wobj;
- }
- }
- }
-